﻿using System;
using System.Collections.Generic;
using System.Linq.Expressions;

namespace Manoso.Data.FluentMap
{
    internal interface IMapJoin
    {
        string SourceAlias { get; }
        string TargetAlias { get; }
        IList<IMapColumn> Sources { get; }
        IList<IMapColumn> Targets { get; }
    }

    public interface IMapJoin<TS, TT>
    {
        /// <summary>
        /// Specify an on criterion for the join clause.
        /// </summary>
        /// <typeparam name="TP">Same property type of the joining tables.</typeparam>
        /// <param name="propertySource">Lambda expression for property of the joining table.</param>
        /// <param name="propertyTarget">Lambda expression for property of the left table.</param>
        /// <param name="targetAlias">Alias of the left table.</param>
        /// <returns></returns>
        IMapJoin<TS, TT> On<TP>(Expression<Func<TS, TP>> propertySource, Expression<Func<TT, TP>> propertyTarget, string targetAlias = null);

        /// <summary>
        /// Specify an on criterion for the join clause.
        /// </summary>
        /// <param name="propertySource">Column name for property of the joining table.</param>
        /// <param name="propertyTarget">Column name for property of the left table.</param>
        /// <param name="targetAlias">Alias of the left table.</param>
        /// <returns></returns>
        IMapJoin<TS, TT> On(string propertySource, string propertyTarget, string targetAlias = null);
    }

    internal class MapJoin<TS, TT> : IMapJoin<TS, TT>, IMapJoin
    {
        public string SourceAlias { get; private set; }
        public string TargetAlias { get; private set; }
        public IList<IMapColumn> Sources { get; private set; }
        public IList<IMapColumn> Targets { get; private set; }

        public MapJoin(string source, string target)
        {
            SourceAlias = source;
            TargetAlias = target;

            Sources = new List<IMapColumn>();
            Targets = new List<IMapColumn>();
        }

        public IMapJoin<TS, TT> On<TP>(Expression<Func<TS, TP>> propertySource, Expression<Func<TT, TP>> propertyTarget, string targetAlias = null)
        {
            if (propertySource == null || propertyTarget == null) return this;

            Sources.Add(new MapColumn(propertySource.GetMemberName(), SourceAlias));
            Targets.Add(new MapColumn(propertyTarget.GetMemberName(), targetAlias ?? TargetAlias));
            return this;
        }

        public IMapJoin<TS, TT> On(string propertySource, string propertyTarget, string targetAlias = null)
        {
            if (propertySource == null || propertyTarget == null) return this;

            Sources.Add(new MapColumn(propertySource, SourceAlias));
            Targets.Add(new MapColumn(propertyTarget, targetAlias ?? TargetAlias));
            return this;
        }
    }
}
